<template>
    <div>
        <audio id="chatAudio">
            <source src="../../assets/voice/notify.ogg" type="audio/ogg">
            <source src="../../assets/voice/notify.mp3" type="audio/mpeg">
            <source src="../../assets/voice/notify.wav" type="audio/wav">
        </audio>
    </div>
</template>

<script>
import Vue from 'vue'
import Lockr from 'lockr'

export default {
    name: "socket",
    data() {
        return {
            is_open_socket: false,
            websocket: null,
            pingInterval: 30,
            connectNum: 1,
            manMade: true,
            //心跳检测
            timeout: 30000,//多少秒执行检测
            heartbeatInterval: null, //检测服务器端是否还活着
            reconnectTimeOut: null, //重连之后多久再次重连
        }
    },
    methods: {
        getWsUrl() {

            const WS_URI = "ws://localhost:65100/ws";
            return WS_URI;
        },
        initWebSocket() { //初始化weosocket
            //ws地址
            const WS_URI = this.getWsUrl();
            this.websocket = new WebSocket(WS_URI);
            console.log("--------------------------------------------------" + WS_URI)
 
            this.is_open_socket = true;
            this.websocket.onmessage = this.websocketOnMessage;
            this.websocket.onopen = this.websocketOnOpen;
            this.websocket.onclose = this.websocketClose;
            Vue.prototype.$websocket = this.websocket;
            this.$store.state.wsStatus = true;
        },
        parseBinaryDataToObject(event) {
            let combinedView = new DataView(event.data);

            // 读取字节数据

            let cmd = combinedView.getUint8(0);

            let version = combinedView.getUint8(1);

            let encrypt = combinedView.getUint8(2);

            let serial = combinedView.getUint8(3);

            let length = combinedView.getUint32(4);

            // 获取字符串数据的位置和长度

            let dataOffset = 8;

            let dataLength = combinedView.byteLength - dataOffset;


            // 创建一个只包含字符串部分的新ArrayBuffer

            let dataBuffer = event.data.slice(dataOffset, dataOffset + dataLength);

            // 解码为字符串
            let decoder = new TextDecoder();

            let dataStr = decoder.decode(dataBuffer);

            //
            // console.log('Received message:');
            //
            // console.log('cmd:', cmd);
            //
            // console.log('version:', version);
            //
            // console.log('encrypt:', encrypt);
            //
            // console.log('serial:', serial);
            //
            // console.log('data:', dataStr);

            return {
                cmd,
                version,
                encrypt,
                serial,
                length,
                data: dataStr
            }
        },
        websocketOnMessage(event) { //数据接收
 
            let userInfo = Lockr.get('UserInfo');
            let token = Lockr.get('authToken');

            const receivedObject = this.parseBinaryDataToObject(event);
            let cmd = receivedObject.cmd;
            let version = receivedObject.version;
            let encrypt = receivedObject.encrypt;
            let serial = receivedObject.serial;
            let bodyLen = receivedObject.length;
            let msgBody = receivedObject.data;
            console.log("当前指令：" + cmd);
            console.log("收到服务端发来的消息: " + msgBody);

            switch (cmd) {
                // 登录成功消息
                case 50:
                    console.log("服务器返回数据：" + JSON.stringify(msgBody));
                    break;
                // 登录 更新用户列表
                case 52:

                    break;
                case 54:

                    break;
                default:
                    this.$store.commit('catchSocketAction', data);
                    break;
            }
        },
        websocketClose(e) {  //关闭
            console.log("websocket连接关闭")
            this.is_open_socket = false;
            clearInterval(this.heartbeatInterval)
            clearInterval(this.reconnectTimeOut)
            if (this.connectNum < 3) {
                this.manMade = false
                this.reconnect();
                this.connectNum += 1
                return;
            } else {
                this.$store.state.wsStatus = false;
                this.connectNum = 1;
                this.websocket = null
            }
            let userInfo = Lockr.get('UserInfo');
            this.$api.commonApi.offlineAPI({ user_id: userInfo.user_id }).then(res => {
                console.log("connection closed (" + e.code + ")");
            })
        },
        websocketOnOpen() {
            let token = Lockr.get('authToken');
            let userInfo = Lockr.get('UserInfo');
            let loginModel = {
                'userNo': userInfo.userNo,
                'appKey': 'e7bbd2cc1bdf45d4bb5cd8077ad40494',
                'systemOs': 'win11',
                'deviceType': 13,
                'createTime': new Date().getTime()

            };
            let jsonData = JSON.stringify(loginModel);
            console.log("发送登录长连接服务器请求：" + jsonData);
            this.websocketSend(this.createMessage(1, 1, 1, 10, jsonData));

            // this.heartbeatInterval = setInterval(() => {
            //     this.websocketSend(this.createMessage(2, 1, 1, 10, { 'from': '' }));
            // }, this.timeout)
        },
        websocketSend(agentData) {//数据发送
            this.websocket.send(agentData);
        },
        checkStatus() {
            if (!this.websocket || [2, 3].includes(this.websocket.readyState)) {
                console.log("未链接！")
                return false;
            }
            return true;
        },
        close() {
            if (!this.is_open_socket) {
                return
            }
            this.websocket.close();
        },
        reconnect() {
            console.log("正在重连...");
            //停止发送心跳
            clearInterval(this.heartbeatInterval)
            //如果不是人为关闭的话，进行重连
            if (!this.is_open_socket && this.manMade == false) {
                console.log("5秒后重新连接...")
                this.reconnectTimeOut = setInterval(() => {
                    this.initWebSocket();
                }, 5000)
            }
        },
        playAudio() {
            const audio = document.getElementById('chatAudio');
            // 从头播放
            audio.currentTime = 0;
            audio.play();
        },
        createMessage(cmd, version, encrypt, serial, dataStr) {
            // 假设所有字节数据都在0-255之间

            const cmdView = new DataView(new ArrayBuffer(1));

            cmdView.setUint8(0, cmd);


            const versionView = new DataView(new ArrayBuffer(1));

            versionView.setUint8(0, version);


            const encryptView = new DataView(new ArrayBuffer(1));

            encryptView.setUint8(0, encrypt);


            const serialView = new DataView(new ArrayBuffer(1));

            serialView.setUint8(0, serial);


            // 将字符串转换为UTF-8编码的ArrayBuffer

            let encoder = new TextEncoder();

            let dataView = encoder.encode(dataStr);


            // 计算并添加4字节的长度字段
            let dataLength = dataView.byteLength;
            const lengthView = new DataView(new ArrayBuffer(4));

            lengthView.setUint32(0, dataLength, false); // 注意endianness（这里是大端序）

            // 合并所有的ArrayBuffer

            let totalLength = 8 + dataView.byteLength;

            let combinedBuffer = new ArrayBuffer(totalLength);

            let combinedView = new DataView(combinedBuffer);


            // 复制每个部分到combinedBuffer中

            let offset = 0;

            combinedView.setUint8(offset++, cmdView.getUint8(0));

            combinedView.setUint8(offset++, versionView.getUint8(0));

            combinedView.setUint8(offset++, encryptView.getUint8(0));

            combinedView.setUint8(offset++, serialView.getUint8(0));

            // 首先复制长度字段
            for (let i = 0; i < 4; i++) {
                combinedView.setUint8(offset++, lengthView.getUint8(i));

            }

            for (let i = 0; i < dataView.byteLength; i++) {
                combinedView.setUint8(offset++, dataView[i]);
            }

            return combinedBuffer;
        },


    },
    created() {
        this.initWebSocket()
    }
}
</script>
